package controller.preprocessor;

import java.awt.event.ActionEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;

import model.cnf.FileCNF;
import model.preprocessor.PreProcessorParameter;
import model.preprocessor.PreProcessorResult;
import model.preprocessor.PreProcessorResultStatus;
import model.preprocessor.RevivalParameter;


/**
 * This class is a implementation of PreProcessor for Revival
 * 
 * @author stephane
 *
 */
public class ReViVal extends PreProcessor {

	public static final String EXEC = "revival";
	public static final String DESCRIPTION = "Result of the revival execution";
		
	//public static final int DEFAULT_RETURN_VALUE = 0; 
	//public static final int ERR_TIMEOUT = 127;
	public static final int ERR_INTERRUPT = 130;
	public static final String TIMEOUT_PREFIX = "Time out is reached...";
	public static final String UNSATISFIABLE_PREFIX = "Proved UNSATISFIABLE";
	
	private RevivalParameter param;
	
	
	public ReViVal(File directory) throws IOException{
		if(!directory.isDirectory() || ! new File(directory, EXEC).isFile())
			throw new IllegalArgumentException();

		param = new RevivalParameter();
		try {
			path = directory.getCanonicalPath() + File.separator + EXEC;
		} catch (IOException e) {
			e.printStackTrace();
			throw new IOException();
		}
		
	}


	@Override
	public boolean checkParameter() {
		return param.basicCheck();
	}


	@Override
	public PreProcessorParameter getPreProcessorParameter() {
		return param;
	}

	
	public RevivalParameter getRevivalParameter() {
		return param;
	}


	@Override
	public String[] getCommandLine(String cnfFile) {
		
		String[] tab = new String[3];
	
		//bash
		tab[0] = "/bin/sh";
		//-c
		tab[1] = "-c";
		
		//chemin de revival
		String tmp = correctFormatForLinux(path);
		//stdin
		tmp += " " + correctFormatForLinux(cnfFile);
		
		if(param.needTimeOut())
		{//timeout
			tmp += " " + String.valueOf(param.getTimeOut() / 1000);
		}
		//redirection
		tmp += " > ";
		//destination, fichier de sortie
		tmp += correctFormatForLinux(param.getOut());
		
		tab[2] = tmp;
	
		return tab;
	}

	@Override
	public boolean hasTimeout() {
		return true;
	}

	@Override
	public PreProcessorResult runPreProcessor(String[] cmd, String fileOutput) {
		PreProcessorResult res = new PreProcessorResult(); 
		
		BufferedReader input = null;
		try{//lance le processus
			res.setBegin(System.currentTimeMillis());
			
			process = Runtime.getRuntime().exec(cmd);

			String line;
			input = new BufferedReader (new InputStreamReader(process.getErrorStream()));

			while ((line = input.readLine()) != null) 
			{ //verifie les stderr
				System.out.println(line);
				res.addStderr(line+"\n");
			}
		}
		catch(IOException e){
			//e.printStackTrace();
			res.setStatus(PreProcessorResultStatus.PROBLEM);
			if(process != null)
				process.destroy();
		}
		finally{
			try{
				if(input != null)
					input.close();
				if(process != null)
					res.setExitVal(process.waitFor());
			}
			catch(Exception e){
				e.printStackTrace();
				res.setStatus(PreProcessorResultStatus.PROBLEM);
			}
			
		}
		//terminer
		res.setEnd(System.currentTimeMillis());
		
		System.out.println("val de retour"+res.getExitVal());
		if(res.getStatus() != PreProcessorResultStatus.PROBLEM)
		{//pas interrompu
			System.out.println("stderr ="+res.getStderr());
			if(res.getStderr().startsWith(TIMEOUT_PREFIX))
				res.setStatus(PreProcessorResultStatus.TIMEOUT_REACHED);
			else
				if(res.getStderr().startsWith(UNSATISFIABLE_PREFIX))
					res.setStatus(PreProcessorResultStatus.UNSATISFIABLE);
				else
					res.setStatus(PreProcessorResultStatus.OK); 
		}
			
		//dernier details
		res.setDescription(DESCRIPTION);
		res.setExportPath(fileOutput);
		try{
			if(res.getStatus() == PreProcessorResultStatus.OK)
			{
				res.setCnf(new FileCNF(fileOutput));
				System.out.println("tension \n "+res.getCnf().getStat());
				//res.setStat(new Stat(res.getCnf()));
			}
		}
		catch (Exception e) {
			e.printStackTrace();
			res.setStatus(PreProcessorResultStatus.PROBLEM);
		}
			
		return res;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource() == timer)
			timer.stop();
	}


}
